package com.handu.luna.core.domain.promotion;

import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.*;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.validation.constraints.Size;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.format.annotation.DateTimeFormat;

import com.handu.luna.core.domain.search.SecKillGroupBuySearch;
import com.handu.luna.core.domain.user.UserRank;

@Entity
public class SecKillGroupBuy extends Promotion {

	public enum SecKillGroupBuyStatus{
		SECKILL("秒杀"),GROUPBUY("团购");
		public String description;	    
		SecKillGroupBuyStatus(final String description) {
	        this.description = description;
	    }
	}
	
	public static final String DELIMITER = ",";
	
	@Size(min=1,max=100, message="秒杀活动名称不能为空或超过100个字符")
	private String secKillGroupBuyName;
	@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
	private Date beginTime;
	@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
	private Date endTime;
	//用户限购数量
	private int userSecKillGroupBuyNumber;
	//商品限购数量
	private int secKillGroupBuyNumber;
	private String userRank;
	private SecKillGroupBuyStatus secKillGroupBuyStatus;
	@Lob
	private String secKillGroupBuyExplain;
	
	@Transient private List<Long> userRankIdList;
	@Transient private List<UserRank> userRankList;
	
	
	
	public SecKillGroupBuy(){}
		
	public SecKillGroupBuy(String secKillGroupBuyName, Date beginTime, Date endTime,
			int secKilGroupBuyNumber, String secKillGroupBuyExplain, SecKillGroupBuyStatus secKillGroupBuyStatus) {
		super();
		this.secKillGroupBuyName = secKillGroupBuyName;
		this.beginTime = beginTime;
		this.endTime = endTime;
		this.secKillGroupBuyNumber = secKilGroupBuyNumber;
		this.secKillGroupBuyExplain = secKillGroupBuyExplain;
		this.secKillGroupBuyStatus = secKillGroupBuyStatus;
	}
	
	@PostLoad
    public void init() {
        if(StringUtils.isNotBlank(userRank)) {
        	userRankList = new ArrayList<>();
        	userRankIdList = new ArrayList<>();
            for (String userRankStrId : this.strToList(userRank)) {
                long userRankId = Long.parseLong(userRankStrId);
                userRankIdList.add(userRankId);
                UserRank ur = context.getUserRankRepository().findOne(userRankId);
                userRankList.add(ur);
            }
        }
    }

    @PrePersist
    public void prePersist() {
        if(CollectionUtils.isNotEmpty(userRankIdList)) {
        	userRank = this.listToStr(userRankIdList);
        }
    }

    public void update() {
        prePersist();
        context.getSecKillGroupBuyRepository().save(this);
    }

    public String listToStr(List<Long> list) {
        StringBuilder sb = new StringBuilder();
        for (Long id : list) {
            sb.append(String.valueOf(id)).append(DELIMITER);
        }
        return sb.toString();
    }

    public List<String> strToList(String arrayString) {
        List<String> list = new ArrayList<String>();
        for(String item : arrayString.split(DELIMITER)) {
            list.add(item);
        }
        return list;
    }

	public String getSecKillGroupBuyName() {
		return secKillGroupBuyName;
	}

	public void setSecKillGroupBuyName(String secKillGroupBuyName) {
		this.secKillGroupBuyName = secKillGroupBuyName;
	}

	public Date getBeginTime() {
		return beginTime;
	}

	public void setBeginTime(Date beginTime) {
		this.beginTime = beginTime;
	}

	public Date getEndTime() {
		return endTime;
	}

	public void setEndTime(Date endTime) {
		this.endTime = endTime;
	}

	public int getSecKillGroupBuyNumber() {
		return secKillGroupBuyNumber;
	}

	public void setSecKillGroupBuyNumber(int secKillGroupBuyNumber) {
		this.secKillGroupBuyNumber = secKillGroupBuyNumber;
	}

	public String getUserRank() {
		return userRank;
	}

	public void setUserRank(String userRank) {
		this.userRank = userRank;
	}

	public SecKillGroupBuyStatus getSecKillGroupBuyStatus() {
		return secKillGroupBuyStatus;
	}

	public void setSecKillGroupBuyStatus(SecKillGroupBuyStatus secKillGroupBuyStatus) {
		this.secKillGroupBuyStatus = secKillGroupBuyStatus;
	}

	public String getSecKillGroupBuyExplain() {
		return secKillGroupBuyExplain;
	}

	public void setSecKillGroupBuyExplain(String secKillGroupBuyExplain) {
		this.secKillGroupBuyExplain = secKillGroupBuyExplain;
	}
	
	public int getUserSecKillGroupBuyNumber() {
		return userSecKillGroupBuyNumber;
	}

	public void setUserSecKillGroupBuyNumber(int userSecKillGroupBuyNumber) {
		this.userSecKillGroupBuyNumber = userSecKillGroupBuyNumber;
	}

	public List<Long> getUserRankIdList() {
		return userRankIdList;
	}

	public void setUserRankIdList(List<Long> userRankIdList) {
		this.userRankIdList = userRankIdList;
	}

	public List<UserRank> getUserRankList() {
		return userRankList;
	}

	public void setUserRankList(List<UserRank> userRankList) {
		this.userRankList = userRankList;
	}
	
	@Override
	public String getStatus() {
		return initStatus(beginTime, endTime);
	}

	public String getSucessFlashMessage(){
		String messagePrefix = (null==this.getId() ?"添加" : "修改");
		try {
			return messagePrefix + this.getSecKillGroupBuyName() + "成功。";
		} catch ( SecurityException e) {
			return messagePrefix + "成功。";
		}
	}
	
	public static Specification<SecKillGroupBuy> selectCondition(SecKillGroupBuySearch secKillGroupBuySearch) {
		return new Specification<SecKillGroupBuy>() {
			@Override
			public Predicate toPredicate(Root<SecKillGroupBuy> root,
					CriteriaQuery<?> query, CriteriaBuilder builder) {

				Predicate predicate = builder.conjunction();
				List<Expression<Boolean>> expressions = predicate.getExpressions();
				
				if (StringUtils.isNotBlank(secKillGroupBuySearch.getSearchName())) {
					expressions.add(builder.or( builder.like(root.<String> get("secKillGroupBuyName"), "%"+ secKillGroupBuySearch.getSearchName() + "%")));			
				}
				
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				Date date1 = null;
				Date date2 = null;
				Date nowdate = null;
				Date now = new Date();
				String nowtime = sdf1.format( now );

				if(StringUtils.isNotBlank(secKillGroupBuySearch.getSearchBeginTime()) && StringUtils.isBlank(secKillGroupBuySearch.getSearchEndTime())){
					try {
						date1 = sdf.parse(secKillGroupBuySearch.getSearchBeginTime());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					expressions.add(builder.greaterThanOrEqualTo(root.get("beginTime"), date1)); 
				}
				
				if(StringUtils.isBlank(secKillGroupBuySearch.getSearchBeginTime())&& StringUtils.isNotBlank(secKillGroupBuySearch.getSearchEndTime())){
					try {
						date2 = sdf.parse(secKillGroupBuySearch.getSearchEndTime());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					expressions.add(builder.lessThanOrEqualTo(root.get("beginTime"), date2)); 
				}

				if(StringUtils.isNotBlank(secKillGroupBuySearch.getSearchBeginTime()) && StringUtils.isNotBlank(secKillGroupBuySearch.getSearchEndTime())){
					
					try {
						date1 = sdf.parse(secKillGroupBuySearch.getSearchBeginTime());
						date2 = sdf.parse(secKillGroupBuySearch.getSearchEndTime());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					expressions.add(builder.greaterThanOrEqualTo(root.get("beginTime"), date1)); 
					expressions.add(builder.lessThanOrEqualTo(root.get("beginTime"), date2));
				}
				
				if(secKillGroupBuySearch.getSearchState()!=0){
					try {
						nowdate = sdf1.parse(nowtime);
					} catch (ParseException e) {
						e.printStackTrace();
					}
					if(secKillGroupBuySearch.getSearchState()==1){
						
						expressions.add(builder.lessThanOrEqualTo(root.get("beginTime"), nowdate)); 
						expressions.add(builder.greaterThanOrEqualTo(root.get("endTime"), nowdate));
						
					}else if(secKillGroupBuySearch.getSearchState()==2){
						
						expressions.add(builder.greaterThanOrEqualTo(root.get("beginTime"), nowdate));
						
					}else if(secKillGroupBuySearch.getSearchState()==3){
						
						expressions.add(builder.lessThanOrEqualTo(root.get("endTime"), nowdate)); 
					}
				}
				
				return query.where(predicate).getRestriction();

			}
		};
	}
	
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public void merge(String[] fields) {
		List<Long> userRankIdList = this.getUserRankIdList();
		if(!this.isNew()){
			Object thisDomainInDB = null;
			try {
                thisDomainInDB = BeanUtils.cloneBean(((JpaRepository) getRepository()).findOne(this.getId()));
			} catch (IllegalAccessException | InstantiationException
					| InvocationTargetException | NoSuchMethodException e1) {
				logger.debug("error in copy merge a domain",e1);
			}			
			for(String field : fields){
				try {
                    String property = BeanUtils.getProperty(this,field);
                    if(field.endsWith("Date") || field.endsWith("beginTime") ||  field.endsWith("endTime")) {
                        Date date = new SimpleDateFormat("EE MMM dd HH:mm:ss 'CST' yyyy", java.util.Locale.US).parse(property);
                        BeanUtils.copyProperty(thisDomainInDB, field, date);
                    }else {
                        BeanUtils.copyProperty(thisDomainInDB, field, property);
                    }
				} catch (IllegalAccessException | InvocationTargetException
						| NoSuchMethodException e) {
					logger.debug("error in copy merge a domain",e);
				} catch (ParseException e) {
                    e.printStackTrace();
                }
            }
			try {
				BeanUtils.copyProperties(this, thisDomainInDB);
			} catch (IllegalAccessException | InvocationTargetException e) {
				logger.debug("error in copy merge a domain",e);
			}
		}
		this.setUserRankIdList(userRankIdList);
	}
	
}
